#coding=utf8
import re

from smtplib import SMTPException

from django.shortcuts import render_to_response, get_object_or_404
from django.db.models import Count, Max, Min, Q
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.http import HttpResponse, HttpResponseRedirect

from ChineKingBlog.blog.models import *
from ChineKingBlog.blog.utils import get_article_abstract, add_weibo_name, access_from_mobile, process_newline, render_mail_str
from ChineKingBlog.blog.forms import *
from ChineKingBlog.blog.weibo import _oauth, weibo
from ChineKingBlog.blog.search import GoogleSearch, ExampleSearch
from ChineKingBlog.settings import EMAIL_HOST_USER, sending_email
from ChineKingBlog.blog.mail import send_mail

_max_font_size = 26
_min_font_size = 10
_minus_font_size = _max_font_size - _min_font_size

_n_per_page = 10

def get_tag_list():
    tag_list = Tag.objects.annotate(n_articles=Count("articles"))[:25]
    
    if tag_list:
        tag_max_articles = tag_list.aggregate(Max("n_articles"))['n_articles__max']
        tag_min_articles = tag_list.aggregate(Min("n_articles"))['n_articles__min']
        for tag in tag_list:
            if tag_max_articles - tag_min_articles > 0:
                tag.font_size = _min_font_size \
                + _minus_font_size*(tag.n_articles-tag_min_articles)/(tag_max_articles-tag_min_articles)
            else:
                tag.font_size = _min_font_size
        
        return tag_list
    
def get_friends():
    comments = add_weibo_name(Comment.objects.filter(visible=True))
    friends = {}
    for comment in comments:
        if len(friends) == 5:
            break
        if friends.get(comment.username) is None:
            friends[comment.username] = comment
            
    return friends.values()
    
def get_intro():
    try:
        return get_article_abstract(User_Info.objects.get(user__username="Chine").info) 
    except ObjectDoesNotExist:
        return ''
    except Exception:
        return ''
    
def get_weibo_client(request):
    access_token = request.session.get('oauth_access_token', None)
    if access_token is not None:
        weibo_client = weibo()
        weibo_client.setToken(access_token.key, access_token.secret)
        return weibo_client
    
def get_logged_weibo_name(request):
    weibo_client = get_weibo_client(request)
    if weibo_client is not None:
        return weibo_client.get_username()
    
class UserData(object):
        def __init__(self, username, email_address, site, avatar):
            self.username = username
            self.email_address = email_address
            self.site = site
            self.avatar = avatar
    
def session_handler(request, save=False):        
    if not save:
        user_data = request.session.get('user_data', None)
        if user_data is not None:
            return user_data.username, user_data.email_address, user_data.site, user_data.avatar
        
    else:
        if request.method == 'POST':
            username = request.POST['username']
            email_address = request.POST['email_address']
            site = request.POST['site']
            avatar = request.POST['avatar']
            
            user_data = request.session.get('user_data', None)
            if user_data is not None:
                changed = False
                if username != user_data.username:
                    user_data.username = username
                    changed = True
                if email_address != user_data.email_address:
                    user_data.email_address = email_address
                    changed = True
                if site != user_data.site:
                    user_data.site = site
                    changed = True
                if avatar != user_data.avatar:
                    user_data.avatar = avatar
                    changed = True
                
                if changed:
                    request.session['user_data'] = user_data
            else:
                user_data = UserData(username, email_address, site, avatar)
                request.session['user_data'] = user_data

def common_data():
    return {
        'cate_list': Category.objects.all(),
        'intro': get_intro(),
        'tag_list': get_tag_list(),
        'comment_list': Comment.objects.filter(visible=True)[:5],
        'friends': get_friends(),
        'popular_article_list': Article.objects.filter(status=2).order_by('-clicks')[:5]
    }
    
def common_data_with_weibo(request):
    if request.session.get('oauth_access_token', None) is None:
        weibo_log = False
    else:
        weibo_log = True
    adict = {
        'weibo_log': weibo_log,
        'weibo_name': get_logged_weibo_name(request)
    }
    adict.update(common_data())
    return adict

contains_chn_reg = re.compile(u"[\u4e00-\u9fa5]")
def check_is_robot(text):
    if contains_chn_reg.search(text) is None:
        return True
    return False

def blog(request, page=1):
    page = int(page) - 1
    
    article_list = Article.objects.filter(status=2)
    for article in article_list:
        article.content_abstract = get_article_abstract(article.content)
        article.n_comment = Comment.objects.filter(Q(visible=True) & Q(article__id=article.id)).count()
    n_articles = article_list.count()
    
    article_list = article_list[page*_n_per_page:(page+1)*_n_per_page]
    
    if request.method == "GET":
        if "from" in request.GET:
            return render_to_response('blog/ajax.html', {'article_list': article_list})
    
    #if access_from_mobile(request):
        #return render_to_response('blog/mobile/base.html', locals())
    
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/index.html', current_data)
    
def article(request, slug):  
    article = get_object_or_404(Article, slug=slug)
    
    article_rss = article.get_absolute_url() + "rss/"
    
    tags = article.tags.all()
    keywords = ", ".join(tag.name for tag in tags)
    
    comment = Comment(article=article)
    user_data = session_handler(request)
    if user_data is not None:
        comment.username = user_data[0]
        comment.email_address = user_data[1]
        comment.site = user_data[2]
        comment.avatar = user_data[3]
    else:
        weibo_client = get_weibo_client(request)
        if weibo_client is not None:
            status = weibo_client.get_status()
            comment.username = '@' + status[1]
            comment.site = status[2]
            comment.avatar = status[3]
 
    form = CommentForm(instance=comment)
    
    nodes = Comment.tree.filter(Q(visible=True)&Q(article__id=article.id))
    i = 0
    for node in nodes:
        if node.level == 0:
            if i%2 == 1:    
                node.classname = "depth-1 thread-alt"
            else:
                node.classname = "depth-1"
            i += 1
        else:
            node.classname = "depth-2"
    nodes = add_weibo_name(nodes)
        
    n_comment = nodes.count()
    
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    if request.GET.get('from') != "admin":
        article.click_once()
    
    return render_to_response('blog/article.html', current_data)

def comments(request, slug):
    article = get_object_or_404(Article, slug=slug)
    
    nodes = Comment.tree.filter(Q(visible=True)&Q(article__id=article.id))
    i = 0
    for node in nodes:
        if node.level == 0:
            if i%2 == 1:    
                node.classname = "depth-1 thread-alt"
            else:
                node.classname = "depth-1"
            i += 1
        else:
            node.classname = "depth-2"
    nodes = add_weibo_name(nodes)
        
    n_comment = nodes.count()
    
    return render_to_response('blog/ajax_comment.html', locals())

def comment(request):
    response = HttpResponse()
    
    send_weibo = False
    if request.POST.get('sendWeibo', '') == 'true':
        send_weibo = True
    
    f = CommentForm(request.POST)
    if f.is_valid():
        comment = f.save(commit=False)
        
        if check_is_robot(comment.content):
            response.write('0')
        else:
            comment.visible = True
            comment.content = process_newline(comment.content)
            comment.save()
        
            session_handler(request, save=True)
        
            access_token = request.session.get('oauth_access_token', None)
            if access_token is not None and send_weibo is True:
                comment.comment_to_weibo(access_token.key, access_token.secret)
            
            from_email = EMAIL_HOST_USER
            to_email = ['chinekingseu@gmail.com']
            plain_text = u''
            html = u''
            subject = u''
            if comment.reply_to_comment is None:
                subject = u'【残阳似血的博客】上的文章刚刚被%s评论了' % comment.username
                plain_text =  render_mail_str(
                    'comment_plaintext.html',
                    (comment.article.title, comment.article.get_absolute_url(),
                     comment.username, comment.content, comment.article.get_absolute_url(), comment.id)
                )
                html = render_mail_str(
                    'comment.html',
                    (comment.article.get_absolute_url(), comment.article.title,
                     comment.username, comment.content, comment.article.get_absolute_url(), comment.id)
                )
            else:
                subject = u'您在【残阳似血的博客】上的评论刚刚被%s回复了' % comment.username
                to_email = [comment.reply_to_comment.email_address]
                plain_text = render_mail_str(
                    'reply_comment_plaintext.html',
                    (comment.article.title, comment.article.get_absolute_url(),
                     comment.username, comment.content, comment.reply_to_comment.content, 
                     comment.article.get_absolute_url(), comment.id)
                )
                html = render_mail_str(
                    'reply_comment.html',
                    (comment.article.get_absolute_url(), comment.article.title,
                     comment.username, comment.content, comment.reply_to_comment.content, 
                     comment.article.get_absolute_url(), comment.id)
                )
        
            if sending_email:
                send_mail(subject, plain_text, from_email, to_email, html=html)
            
            response.write('1')       
    else:
        response.write('0') 
    
    return response

def categories(request):
    cates = Category.objects.all()
    
    for cate in cates:
        cate.articles = Article.objects.filter(Q(status=2) & Q(category__id=cate.id))[:5]
        
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/cates.html', current_data)
    

def category(request, slug, page=1):
    page = int(page) - 1
    
    cate = get_object_or_404(Category, slug=slug)
    
    article_list = Article.objects.filter(Q(status=2)&Q(category__slug=slug))
    for article in article_list:
        article.content_abstract = get_article_abstract(article.content)
        article.n_comment = Comment.objects.filter(Q(visible=True) & Q(article__id=article.id)).count()
    n_articles = article_list.count()
    
    article_list = article_list[page*_n_per_page:(page+1)*_n_per_page]
    
    if request.method == "GET":
        if "from" in request.GET:
            return render_to_response('blog/ajax.html', {'article_list': article_list})
    
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/category.html', current_data)
    
def tag(request, slug, page=1):
    page = int(page) - 1
    
    tag = get_object_or_404(Tag, slug=slug)
    
    article_list = tag.articles.filter(status=2)
    for article in article_list:
        article.content_abstract = get_article_abstract(article.content)
        article.n_comment = Comment.objects.filter(Q(visible=True) & Q(article__id=article.id)).count()
    n_articles = article_list.count()
    
    article_list = article_list[page*_n_per_page:(page+1)*_n_per_page]
    
    if request.method == "GET":
        if "from" in request.GET:
            return render_to_response('blog/ajax.html', {'article_list': article_list})
    
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/tag.html', current_data)

def about(request):
    user = User_Info.objects.get(user__username="Chine")
    
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/about.html', current_data)

def contact(request, page=1):
    message = Message()
    try:
        user_data = session_handler(request)
        if user_data is not None:
            message.username = user_data[0]
            message.email_address = user_data[1]
            message.site = user_data[2]
            message.avatar = user_data[3]
        else:
            weibo_client = get_weibo_client(request)
            if weibo_client is not None:
                status = weibo_client.get_status()
                message.username = '@' + status[1]
                message.site = status[2]
                message.avatar = status[3]
    except Exception:
        pass
        # print Exception.message
    form = MessageForm(instance=message)
        
    page = int(page) - 1
    
    messages_list = Message.objects.filter(visible=True)  
    n_message = messages_list.count()   
    messages = messages_list[page*_n_per_page:(page+1)*_n_per_page]
    messages = add_weibo_name(messages)
    
    if request.method == "GET":
        if "from" in request.GET:
            return render_to_response('blog/ajax_contact.html', {'messages': messages})
   
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/contact.html', current_data)

def message(request):
    response = HttpResponse()
    
    send_weibo = False
    if request.POST.get('sendWeibo', '') == 'true':
        send_weibo = True
    
    f = MessageForm(request.POST)
    if f.is_valid():
        message = f.save(commit=False)
        
        if check_is_robot(message.content):
            response.write('0')
        else:
            message.visible = True
            message.content = process_newline(message.content)
            message.save()
        
            session_handler(request, save=True)
        
            access_token = request.session.get('oauth_access_token', None)
            if access_token is not None and send_weibo is True:
                message.message_to_weibo(access_token.key, access_token.secret)
        
            from_email = EMAIL_HOST_USER
            to_email = ['chinekingseu@gmail.com']
            subject = u'【残阳似血的博客】刚刚收到%s的留言' % message.username
            plain_text = render_mail_str(
                'message_plaintext.html',
                (message.username, message.content, message.id)
            )
            html = render_mail_str(
                'message.html',
                (message.username, message.content, message.id)
            )
        
            if sending_email:
                send_mail(subject, plain_text, from_email, to_email, html=html)
        
            response.write('1')       
    else:
        response.write('0') 
    
    return response

def search(request):
    query = request.GET.get('q', '')
    query = query.strip().replace('Search...', '')
    
    page = int(request.GET.get('page', 1))
    start = (page - 1) * _n_per_page + 1
    end = page * _n_per_page
    
    count = 0
    if len(query) > 0:
        #search = GoogleSearch(query)
        search = GoogleSearch(query, page)
        count, results = search()
        if count - start + 1 < _n_per_page:
            end = count
        
        if request.GET.get('from', '') == 'ajax':
            return render_to_response('blog/ajax_search.html', {'results': results})
        
    page = int(page) - 1
    current_data = locals()
    current_data.update(common_data_with_weibo(request))
    
    return render_to_response('blog/search.html', current_data)

def email(request):
    response = HttpResponse()
    
    username = request.POST.get('name', '')
    email = request.POST.get('email', '')
    to_email = request.POST.get('toemail', '')
    content = request.POST.get('message', '')
    from_email = EMAIL_HOST_USER
    
    success = True
    mails = to_email.replace(u'，', u',').split(u',')
    f = forms.EmailField()
    for mail in mails:
        try:
            f.clean(mail)
        except ValidationError:
            success = False
    try:
        f.clean(email)
    except ValidationError:
        susccess = False    
    
    if success:
        try:
            subject = u"好友" + username + u'向您推荐残阳似血的博客文章'
            plain_text = u"您的好友" + username + u"（" + email + u"）说：" + content
            html = u"您的好友<a title='' href='mailto:" + \
                email +"'>" + username + \
                u"</a>说：</p><p>" + content \
                + u"</p><p><hr />请勿直接回复本邮件</p><p><a title='残阳似血的博客' href='http://qinxuye.me'>残阳似血的博客</a>，欢迎订阅博客<a title='' href='http://qinxuye.me/rss/'>rss</p>"
            send_mail(subject, plain_text, from_email, mails, html=html)
            success = True
        except SMTPException:
            success = False
        except Exception:
            success = False
        
    if success:
        response.write('1')
    else:
        response.write('0')
    
    return response

def _get_referer_url(request):
    referer_url = request.META.get('HTTP_REFERER', '/')
    host = request.META['HTTP_HOST']
    if referer_url.startswith('http') and host not in referer_url:
        referer_url = '/'
    return referer_url

def log(request):
    back_to_url = _get_referer_url(request)
    request.session['login_back_to_url'] = back_to_url
    
    login_backurl = request.build_absolute_uri('/logincheck')
    auth_client = _oauth()
    auth_url = auth_client.get_authorization_url_with_callback(login_backurl)
    request.session['oauth_request_token'] = auth_client.request_token
    
    return HttpResponseRedirect(auth_url)

def log_check(request):
    verifier = request.GET.get('oauth_verifier', None)
    auth_client = _oauth()
    
    request_token = request.session['oauth_request_token']
    del request.session['oauth_request_token']
    
    auth_client.set_request_token(request_token.key, request_token.secret)
    access_token = auth_client.get_access_token(verifier)
    
    request.session['oauth_access_token'] = access_token
    
    back_to_url = request.session.get('login_back_to_url', '/')
    return HttpResponseRedirect(back_to_url)

def logout(request):
    try:
        del request.session['oauth_access_token']
    except KeyError:
        pass
    back_to_url = _get_referer_url(request)
    
    return HttpResponseRedirect(back_to_url)